import type { ComponentMeta } from '@/definitions/type'
import { useDesignStore } from '@/stores'
import { computed, effectScope, onMounted, ref, watch, type WatchSource } from 'vue'

interface Prefix {
  (className: string): string
}
interface SwiperOpts {
  [key: string]: any
}
interface SwiperInstance {
  [key: string]: any
}
interface UseSwiperOpts {
  prefix: Prefix
  props: { render: ComponentMeta }
  watchSourceForUpdate: WatchSource<any>
  swiperOpts?: SwiperOpts
  /** @default true */
  reInitOnPlatformChange?: boolean
}
export function useSwiper(opts: UseSwiperOpts) {
  const { prefix, props, watchSourceForUpdate, swiperOpts, reInitOnPlatformChange = true } = opts
  const swiperCls = prefix('swiper')
  const swiper = ref<Nullable<SwiperInstance>>(null)
  const swiperId = computed(() => {
    return swiperCls + props.render.id
  })
  const designStore = useDesignStore()
  const platform = computed(() => designStore.config.platform)
  const scope = effectScope(true)
  scope.run(() => {
    watch(watchSourceForUpdate, () => {
      updateSwiper()
    }, {
      deep: true,
      flush: 'post',
    })
    if (reInitOnPlatformChange) {
      watch(platform, () => {
        initializeSwiper()
      }, {
        immediate: false,
        flush: 'post',
      })
    }
  })
  onMounted(() => {
    initializeSwiper()
  })
  function isContainerConneted() {
    return document.querySelector(`#${swiperId.value}`) instanceof Element
  }
  function initializeSwiper() {
    if (!isContainerConneted()) {
      swiper.value = null
      return
    }
    swiper.value = new window.Swiper(`#${swiperId.value}`, {
      autoplay: true,
      pagination: {
        el: '.swiper-pagination',
        clickable: true,
        bulletClass: ['swiper-pagination-bullet', prefix('swiper-pagination-bullet')].join(' '),
        bulletActiveClass: ['swiper-pagination-bullet-active', prefix('swiper-pagination-bullet-active')].join(' '),
      },
      ...swiperOpts,
    })
  }
  function updateSwiper() {
    if (isContainerConneted()) {
      if (swiper.value) {
        swiper.value.update()
        swiper.value.enable()
      }
      else {
        initializeSwiper()
      }
    }
    else {
      swiper.value = null
    }
  }
  return {
    swiperCls,
    swiper,
    swiperId,
    updateSwiper,
    initializeSwiper,
  }
}
